#pragma once
#include <poll.h>
#include <unistd.h>
#include <sys/times.h>
#include <sys/types.h>
#include "Socket.hpp"
#include "log.hpp"

uint16_t defaultport = 8888;
std::string defaultip = "127.0.0.1";
#define fd_max_num 1024
int defaultfd = -1;
int non_event = 0;

class Poll
{
public:
    Poll(uint16_t port = defaultport, std::string ip = defaultip)
        : port_(port), ip_(ip)
    {
        for (int i = 0; i < fd_max_num; i++)
        {
            _events_fds[i].fd = defaultfd;
            _events_fds[i].events = non_event;
            _events_fds[i].revents = non_event;
        }
    }

    bool Init()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();
    }

    void Accepter()
    {
        std::string clientip;
        uint16_t clientiport;
        int sock = listensock_.Accept(&clientip, &clientiport);
        lg(INFO, "sock fd: %d, ip: %s, port: %d", sock, clientip.c_str(), clientiport);
        if (sock < 0)
            lg(WARNING, "Accpet error");

            
        int pos = 1;
        for (; pos < fd_max_num; pos++)
        {
            if (_events_fds[pos].fd != defaultfd)
                continue;
            else
                break;
        }

        if (pos > fd_max_num)
        {
            lg(WARNING, "server is full, close %d now!", sock);
            close(sock);
        }
        else
        {
            _events_fds[pos].fd = sock;
            _events_fds[pos].events = POLLIN;
            
            Printfd();
        }
    }
    void Printfd()
    {
        std::cout << "fd: ";
        for (int i = 1; i < fd_max_num; i++)
        {
            if (_events_fds[i].fd != defaultfd)
                std::cout << _events_fds[i].fd << " ";
        }
        std::cout << std::endl;
    }

    void recver(int fd,int pos)
    {
        char buffer[1024];
        ssize_t n = read(fd, &buffer, sizeof(buffer));
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer << std::endl;
        }
        else
        {
            close(fd);
            _events_fds[pos].fd = defaultfd;
        }
    }

    void Dispatcher()
    {

        for (int i = 0; i < fd_max_num; i++)
        {

            int fd = _events_fds[i].fd;
            if (fd == defaultfd)
                continue;

            if (_events_fds[i].revents & POLLIN)
            {
                if (fd == listensock_.GetFd())
                {
                    Accepter();
                }
                else
                {
                    recver(fd,i);
                }
            }
        }
    }

    void Start()
    {
        _events_fds[0].fd = listensock_.GetFd();
        _events_fds[0].events = POLLIN;
        int timeout = 3000; 
        while (true)
        {

            int n = poll(_events_fds,fd_max_num,timeout);

            switch (n)
            {
            case -1:
                std::cout << "selcet error" << std::endl;
                break;
            case 0:
                std::cout << "timeout......" <<std::endl;
                break;
            default:
                std::cout << "Get a new Link...." << std::endl;
                Dispatcher();
                break;
            }
        }
    }

    ~Poll()
    {
    }

private:
    Sock listensock_;
    uint16_t port_;
    std::string ip_;
    struct pollfd _events_fds[fd_max_num];
};